package com.promis.util;

import android.util.Log;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.Date;
import java.util.List;

/**
 * Created by jidanbo on 2018/1/18.
 */

public class JsonUtils {

    public static <T> String toJson(T t, final String...filterProperties) {
        GsonBuilder builder = new GsonBuilder().registerTypeAdapter(Date.class, new JsonDateTypeAdapter());
		builder.setExclusionStrategies(new ExclusionStrategy() {
			@Override
			public boolean shouldSkipField(FieldAttributes f) {
                if (!CollectionUtils.isNullOrEmpty(filterProperties)) {
                    for (String fp : filterProperties) {
                        return f.getName().equals(fp);
                    }
                }
                return false;
			}

			@Override
			public boolean shouldSkipClass(Class<?> incomingClass) {
				return false;
			}
		});
        Gson gson = builder.create();
        return gson.toJson(t);
    }

    public static <T> T fromJson(String json, Class<T> valueType) {
        try {
            GsonBuilder builder = new GsonBuilder().registerTypeAdapter(Date.class, new JsonDateTypeAdapter());
            Gson gson = builder.create();
            return gson.fromJson(json, valueType);
        } catch (RuntimeException ex) {
            Log.e("JsonUtils", ex.getMessage());
            return null;
        }
    }

    public static <T> T fromJson(String json, Type valueType) {
        try {
            GsonBuilder builder = new GsonBuilder().registerTypeAdapter(Date.class, new JsonDateTypeAdapter());
            Gson gson = builder.create();
            return gson.fromJson(json, valueType);
        } catch (RuntimeException ex) {
            Log.e("JsonUtils", ex.getMessage());
            return null;
        }
    }

    public static List<Integer> toList$Integer(String json) {
        try {
            if (StringUtils.isNullOrEmpty(json)) return null;
            Type type = new TypeToken<List<Integer>>(){}.getType();
            return JsonUtils.fromJson(json, type);
        } catch (RuntimeException ex) {
            Log.e("JsonUtils", ex.getMessage());
            return null;
        }
    }

    public static List<String> toList$String(String json) {
        try {
            if (StringUtils.isNullOrEmpty(json)) return null;
            Type type = new TypeToken<List<String>>(){}.getType();
            return JsonUtils.fromJson(json, type);
        } catch (RuntimeException ex) {
            Log.e("JsonUtils", ex.getMessage());
            return null;
        }
    }

    public static <T> List<T> toList$T(String json, TypeToken<List<T>> typeToken) {
        try {
            if (StringUtils.isNullOrEmpty(json)) return null;
            Type type = typeToken.getType();
            return JsonUtils.fromJson(json, type);
        } catch (RuntimeException ex) {
            Log.e("JsonUtils", ex.getMessage());
            return null;
        }
    }

    public static class JsonDateTypeAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {

        public JsonElement serialize(Date src, Type arg1, JsonSerializationContext arg2) {
            if (src == null) return null;
            String dateFormatAsString = DateUtils.format(src, "yyyy-MM-dd HH:mm:ss.SSS");
            return new JsonPrimitive(dateFormatAsString);
        }

        public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
            if (!(json instanceof JsonPrimitive)) {
                throw new JsonParseException("The date should be a string value");
            } else if (json == null || "".equals(json.getAsString())) {
                return null;
            }

            Date date = DateUtils.parse(json.getAsString(), "yyyy-MM-dd HH:mm:ss.SSS");
            if (date == null) date = DateUtils.parse(json.getAsString(), "yyyy-MM-dd HH:mm:ss");
            if (date == null) date = DateUtils.parse(json.getAsString(), "yyyy-MM-dd HH:mm");
            if (date == null) date = DateUtils.parse(json.getAsString(), "yyyy-MM-dd");
            if (date == null) date = DateUtils.parse(json.getAsString(), "HH:mm:ss.SSS");
            if (date == null) date = DateUtils.parse(json.getAsString(), "HH:mm:ss");
            if (date == null) date = DateUtils.parse(json.getAsString(), "HH:mm");
            if (date == null) throw new JsonParseException("时间数据格式有误");
            return date;
        }
    }
}
